package com.payment.controller.callback;

import com.alibaba.fastjson.JSON;
import com.payment.entity.agatewaytobeijing.JsonConstant;
import com.payment.entity.agatewaytobeijing.order.RequestPurchaseService;
import com.payment.entity.agatewaytobeijing.order.response.OrderResponse;
import com.payment.entity.common.OrderPaymentManager;
import com.payment.entity.payresults.travis.request.TravisCallbackRequest;
import com.payment.entity.payresults.travis.request.TravisCallbackRequestData;
import com.payment.entity.payresults.travis.request.TravisCallbackRequestTradeData;
import com.payment.entity.payresults.travis.response.TravisCallbackResponse;
import com.payment.entity.payresults.travis.response.TravisCallbackResponseData;
import com.payment.service.OrderPaymentManagerService;
import com.payment.service.PartnerService;
import com.payment.service.SequenceService;
import com.payment.service.agatewaytobeijing.GatewayToBeijingService;
import com.payment.utils.Constant;
import com.payment.utils.MD5;
import com.payment.utils.UtilsInterfacesPackage;
import com.payment.utils.mail.SendMailUtil;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.MailException;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.text.SimpleDateFormat;
import java.util.Date;

@RestController
@Api(tags = "译翼通-1.0订单支付结果回调接口")
/**
 * 1，译翼通-客户自行支付之后将结果回传给领科的接口：
 *
 * 2，适用于老的客户：译翼通
 *
 * 3，相同的接口在 2.0时接口地址是：payment/callback
 *
 * 4，更新的数据表为：user_order_payment_manager_t，user_bound_payment_order_t；
 *
 * 5，更新的数据库为：links
 *
 * @author lm
 * @date 2019/11/06
 * @date 2021/05/28  最新一次修改的时间
 */
@Slf4j
public class CallbackController {
    /**
     * 3.0接口：请求北京企业网关的地址
     */
    @Value("${jsonIot3.JSON_BASE_URL}")
    private String jsonBaseURL3;
    @Autowired
    private OrderPaymentManagerService orderPaymentManagerService;
    @Autowired
    private SequenceService sequenceService;
    @Autowired
    PartnerService partnerService;
    @Autowired
    GatewayToBeijingService toBeijingService;
    @Autowired
    JavaMailSenderImpl javaMailSender;

    /*支付方式:1-微信支付，2-payPal支付，3-oceanPay支付,4-第三方自行支付*/

    @PostMapping(value = "/callback", produces = "application/json;charset=utf-8")
    @CrossOrigin
    public String callback(@RequestBody TravisCallbackRequest request) {
        // 1，生成流水号
        String connSeqNo = sequenceService.getPackageTaskNo();
        // 2,生成当前时间戳
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String curTime = df.format(new Date());
        //3，定义回报报文
        String jsonString;
        UtilsInterfacesPackage utils = new UtilsInterfacesPackage();
        if (StringUtils.isBlank(JSON.toJSONString(request))) {
            log.info("请求报文不合法:requestStr为空");
            jsonString = utils.dataWeiKong(connSeqNo, curTime);
            return jsonString;
        }
        String requestStr = JSON.toJSONString(request);
        log.info("第三方自行支付结果回调：" + requestStr);
        if (null == request.getSign()) {
            log.info("请求报文不合法:sign为空");
            jsonString = utils.dataWeiKong(connSeqNo, curTime);
            return jsonString;
        }

        String requestSign = request.getSign();
        if (null == request.getData()) {
            log.info("请求报文不合法:data为空");
            jsonString = utils.dataWeiKong(connSeqNo, curTime);
            return jsonString;
        }

        TravisCallbackRequestData requestData = request.getData();
        if (StringUtils.isBlank(requestData.getPartnerCode()) || StringUtils.isBlank(requestData.getConnSeqNo()) || StringUtils.isBlank(requestData.getTradeTime()) ||
                StringUtils.isBlank(requestData.getToken()) || StringUtils.isBlank(requestData.getTradeType()) || StringUtils.isBlank(requestData.getLang()) || null == requestData.getTradeData()) {
            log.info("请求报文不合法:data参数不合法");
            jsonString = utils.dataWeiKong(connSeqNo, curTime);
            return jsonString;
        }

        String partnerCode = requestData.getPartnerCode();
        String connSeqNo1 = requestData.getConnSeqNo();
        String tradeTime = requestData.getTradeTime();
        String token = requestData.getToken();
        String tradeType = requestData.getTradeType();

        // 将请求体json转成String
        String str = JSON.toJSONString(requestData);
        // 将Str拿去计算签名
        String sign = utils.calculateSignature(str);
        if (!requestSign.equalsIgnoreCase(sign)) {
            log.info("签名验证失败！");
            jsonString = utils.publicMessage(connSeqNo1, partnerCode, tradeTime, token, tradeType);
            return jsonString;
        }

        TravisCallbackRequestTradeData requestTradeData = requestData.getTradeData();
        if (StringUtils.isBlank(requestTradeData.getOrderId()) || StringUtils.isBlank(requestTradeData.getPaymentStatus()) || StringUtils.isBlank(requestTradeData.getPaymentCurrency()) || StringUtils.isBlank(requestTradeData.getRequestOrderId())) {
            log.info("请求报文不合法:orderId和amount不可以为空！");
            jsonString = utils.dataWeiKong(connSeqNo, curTime);
            return jsonString;
        }
        /*主要参数解析，先前使用orderId是因为先去北京取到了orderId，现在用orderNo深圳自己生成的假的单号，所以加了一个参数  String orderId = requestTradeData.getOrderId();*/
        String orderNo = requestTradeData.getOrderId();
        String paymentStatus = requestTradeData.getPaymentStatus();
        String paymentAmount = requestTradeData.getPaymentAmount();
        String paymentCurrency = requestTradeData.getPaymentCurrency();
        String requestOrderId = requestTradeData.getRequestOrderId();

        //把传回来的数据入库
        Integer count = orderPaymentManagerService.findOrderCodeByNotify(orderNo);
        if (count < 1) {
            /*说明当前没有插入记录 ，现在就去插入.支付方式:1-微信支付，2-payPal支付，3-oceanPay支付,4-第三方自行支付;成功就将PayRst设为1；不插入就数据库默认0;成功就要通知，数据库就记1，不成功就不通知数据库会默认0*/
            OrderPaymentManager paymentOrder = new OrderPaymentManager();
            paymentOrder.setPayRst(paymentStatus);
            paymentOrder.setIsNotify("1");
            paymentOrder.setPayType(Constant.PAY_QITA);
            /*paymentOrder.setOrderId(orderId);*/
            paymentOrder.setOrderNo(orderNo);
            paymentOrder.setAmount(paymentAmount);
            paymentOrder.setOrderCurrency(paymentCurrency);
            paymentOrder.setRequestOrderId(requestOrderId);
            Integer co = orderPaymentManagerService.updatePayRstById(paymentOrder);
            if (co > 0) {
                log.info("OrderPaymentManager表支付结果入库完成！");
                //去数据库取订单数据准备去做订购
                OrderPaymentManager userOrder = orderPaymentManagerService.queryOrderByOrderId(orderNo, requestOrderId);
                if (null != userOrder) {
                    String secret = partnerService.findSecretByPartnerCode(partnerCode);
                    /*以取到数据为最终目的去处理订购套餐，第三方支付在去订购时候的payType赋值为0*/
                    RequestPurchaseService purchase = RequestPurchaseService.builder()
                            .secret(secret).partnerCode(userOrder.getPartnerCode()).deviceCode(userOrder.getDeviceId())
                            .packageCode(userOrder.getPackageCode()).packageName(userOrder.getPackageName()).packageType(userOrder.getPackageType())
                            .orderPeriod(userOrder.getOrderPeriod()).amount(userOrder.getAmount()).payType("0").build();
                    /*发起订购套餐*/
                    OrderResponse orderPackage = toBeijingService.order(purchase, "0");
                    /*先看接口订购套餐接口成功的情况*/
                    if (null != orderPackage && null != orderPackage.getCode() && JsonConstant.RET_CODE_0000.equals(orderPackage.getCode()) && null != orderPackage.getData() && StringUtils.isNotBlank(orderPackage.getData().getOrder_id())) {
                        /*订购套餐成功获取到orderId*/
                        log.info(userOrder.getDeviceId() + ":订购套餐：" + userOrder.getPackageName() + "：获取订单：" + orderPackage.getData().getOrder_id() + ":成功！");
                        /*现在去更新数据库的orderId字段*/
                        OrderPaymentManager order = new OrderPaymentManager();
                        order.setOrderId(orderPackage.getData().getOrder_id());
                        order.setOrderStartDate(orderPackage.getData().getOrder_start_date());
                        order.setOrderExpireDate(orderPackage.getData().getOrder_expire_date());
                        order.setOrderNo(orderNo);
                        Integer cou = orderPaymentManagerService.updateOrderId(order);
                        if (cou > 0) {
                            log.info("订单号：" + orderPackage.getData().getOrder_id() + ":数据表内更新成功！");
                        } else {
                            log.info("订单号：" + orderPackage.getData().getOrder_id() + ":数据表内更新失败！");
                            /*最后拿到orderId更新数据库时失败*/
                            sendPrivateMail(orderNo, requestOrderId, "译翼通订购下单", "最后拿到orderId更新数据库时失败");
                        }
                    } else {
                        /*再看接口订购套餐接口订购失败的情况*/
                        /*发送异常邮件*/
                        sendMail(userOrder.getDeviceId(), userOrder.getPackageName(), userOrder.getOrderPeriod(), userOrder.getPartnerName(), "", "订购流量套餐", "接口连接超时或其他原因导致订购失败");
                    }
                }
            } else {
                /*回调的数据入库失败*/
                /*发送异常邮件*/
                sendPrivateMail(orderNo, requestOrderId, "译翼通支付结果回调", "数据回调orderNo结果入库失败");
            }
        } else {
            /*回调的订单跟数据库对不上，是不是回调有误？*/
            /*发送异常邮件*/
            sendPrivateMail(orderNo, requestOrderId, "译翼通支付结果回调", "数据回调orderNo在数据库内无此记录");
        }
        /*给客户的响应始终都是成功的响应*/
        TravisCallbackResponseData data = new TravisCallbackResponseData();
        data.setConnSeqNo(connSeqNo1);
        data.setPartnerCode(partnerCode);
        data.setToken(token);
        data.setTradeType(tradeType);
        data.setTradeTime(tradeTime);
        data.setTradeRstCode(1000);
        data.setTradeRstMessage("success");

        TravisCallbackResponse responseWeiXinPay = new TravisCallbackResponse();
        responseWeiXinPay.setData(data);
        responseWeiXinPay.setSign(MD5.calcMD5(JSON.toJSONString(data)));
        // 返回给调用者的报文
        jsonString = JSON.toJSONString(responseWeiXinPay);
        log.info("响应报文：" + jsonString);
        return jsonString;
    }

    /***
     * 发送异常邮件方法
     * 发给service@linksfield.net
     * @param deviceId
     * @param packageName
     * @param orderId
     * @param type
     * @param message
     */
    public void sendMail(String deviceId, String packageName, String orderPeriod, String partnerName, String orderId, String type, String message) {
        try {
            String sendText = "卡片iccId:" + deviceId + "\n" +
                    "套餐名称:" + packageName + "\n" +
                    "订购周期:" + orderPeriod + "\n" +
                    "企业名称:" + partnerName + "\n" +
                    "订单编码:" + orderId + "\n" +
                    "操作类型:" + type + "\n" +
                    "异常描述:" + message + "\n";
            javaMailSender.send(new SendMailUtil().sendIdentifyingCode("ISCETT异步订购套餐异常处理", sendText));
            log.info(orderId + ":异常邮件发送成功");

        } catch (MailException e) {
            log.info("邮件发送出现异常：" + e);
        }
    }

    /**
     * 发送异常邮件方法
     * 发给1556723929@qq.com
     *
     * @param orderNo
     * @param requestOrderId
     * @param type
     * @param message
     */
    private void sendPrivateMail(String orderNo, String requestOrderId, String type, String message) {
        try {
            String sendText = "订单号:" + orderNo + "\n" +
                    "客户订单号:" + requestOrderId + "\n" +
                    "操作类型:" + type + "\n" +
                    "异常描述:" + message + "\n";
            javaMailSender.send(new SendMailUtil().sendIdentifyingPrivate("ISCETT异步订购套餐异常处理", sendText));
            log.info(orderNo + ":异常邮件发送成功");
        } catch (MailException e) {
            log.info("邮件发送出现异常：" + e);
        }
    }
}
